package com.turing.mission.service.impl;
import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.turing.mission.entity.MyMission;
import com.turing.mission.feign.AuthService;
import com.turing.mission.feign.CustomerService;
import com.turing.mission.mapper.MissionMapper;
import com.turing.mission.service.MissionService;
import com.turing.mission.service.MyMissionService;
import com.turing.mission.mapper.MyMissionMapper;
import enums.ErrorCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import result.Result;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
* @author dell
* @description 针对表【my_mission】的数据库操作Service实现
* @createDate 2023-05-09 20:20:09
*/
@Service
public class MyMissionServiceImpl extends ServiceImpl<MyMissionMapper, MyMission>
    implements MyMissionService{

    @Resource
    private CustomerService customerService;
    @Resource
    private AuthService authService;
    @Resource
    private HttpServletRequest request;
    @Resource
    private MissionService missionService;
    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Result myMissionSave(JSONObject jsonObject) {
        String missionId = jsonObject.getString("missionId");
        //获取token
        String token = request.getHeader("Authorization");
        String tokenHead = "Bearer ";
        token = token.substring(tokenHead.length());
        System.out.println("token = " + token);
        //根据token获取cusId
        Result infoByToken = authService.getUserInfoByToken(token);
        JSONObject json = JSON.parseObject(JSON.toJSONString(infoByToken.getData()));
        String cusId = json.getString("username");

        Result result = customerService.geCusById(cusId);
        System.out.println("result = " + result);
        JSONObject jsonObject1 = JSON.parseObject(JSON.toJSONString(result.getData()));
        System.out.println("111"+missionService.getById(missionId));
        System.out.println("jsonObject1 = " + jsonObject1.getDouble("cus_prestige"));
        //威信度不足级别
        if(jsonObject1.getDouble("cusPrestige") < missionService.getById(missionId).getMissionLevel()){
            return Result.fail(2,"级别不够！");
        }
        //同一个任务，一个客户只可领取一次
        LambdaQueryWrapper<MyMission> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MyMission::getMissionId,missionId)
                .eq(MyMission::getCusId,cusId);
        List<MyMission> myMissions = this.baseMapper.selectList(wrapper);
        if(!myMissions.isEmpty()){
            return Result.fail(3,"你已领取该任务！");
        }

        //任务领取人数
        LambdaQueryWrapper<MyMission> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(MyMission::getMissionId,missionId);
        Integer count = Math.toIntExact(this.baseMapper.selectCount(wrapper1));
        System.out.println("count = " + count);
        int i = 0;
        //任务的同步锁
        ValueOperations stringOps = redisTemplate.opsForValue();
        Long now = System.currentTimeMillis();
        //5秒内不断尝试获得锁
        while (System.currentTimeMillis()<(now+5000)){
            if(stringOps.setIfAbsent("missionId::"+missionId,"1",3, TimeUnit.SECONDS)){
                //若任务领取人数达到上限，无法领取
                if(count.equals(missionService.getById(missionId).getCustomerCount())){
                    return Result.fail(4,"该任务领取人数已达上限！");
                }else {
                    MyMission myMission = new MyMission();
                    myMission.setMmsiId(UUID.randomUUID().toString());
                    myMission.setMissionId(missionId);
                    myMission.setCusId(cusId);
                    myMission.setMmisState("P");
                    myMission.setMoneyReward(missionService.getById(missionId).getMissionAmount());
                    myMission.setSignState(0);
                    myMission.setSignDate(null);
                    i = this.baseMapper.insert(myMission);
                }
                //释放锁
                redisTemplate.delete("missionId::"+missionId);
                break;
            }
        }
        if(i > 0){
            return Result.success();
        }
        return Result.fail(ErrorCode.ERROR_ADD);
    }

    @Override
    public Result myMissionList(String mtId,String missonId,Integer sortType, Integer orderType, Integer pageNum, Integer pageSize) {
        //获取token
        String token = request.getHeader("Authorization");
        String tokenHead = "Bearer ";
        token = token.substring(tokenHead.length());
        System.out.println("token = " + token);
        //根据token获取id
        Result infoByToken = authService.getUserInfoByToken(token);
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(infoByToken.getData()));
        String cusId = jsonObject.getString("username");
        if (pageNum!=null && pageSize!=null){
            PageHelper.startPage(pageNum,pageSize);
        }
        List<String> misIds = new ArrayList<>();
        Map redisData = new HashMap();
        ZSetOperations zsetOps = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple> redisSet;
        if (sortType == 2){
            if (pageNum!=null){
                if (orderType==1){
                    redisSet = zsetOps.reverseRangeWithScores("missionComments", (pageNum - 1) * pageSize, pageNum * pageSize - 1);
                }else{
                    redisSet = zsetOps.rangeWithScores("missionComments", (pageNum - 1) * pageSize, pageNum * pageSize - 1);
                }
            }else{
                if (orderType==1){
                    redisSet = zsetOps.reverseRangeWithScores("missionComments", 0, -1);
                }else{
                    redisSet = zsetOps.rangeWithScores("missionComments", 0, -1);
                }
            }
            for (ZSetOperations.TypedTuple typedTuple : redisSet) {
                misIds.add((String) typedTuple.getValue());
            }
        }else{
            redisSet = zsetOps.rangeWithScores("missionComments", 0, -1);
            for (ZSetOperations.TypedTuple typedTuple : redisSet) {
                redisData.put(typedTuple.getValue(), typedTuple.getScore());
            }
        }
        List<Map> list = this.baseMapper.select(cusId,mtId,missonId,sortType,orderType,pageNum,pageSize);
        if (sortType != 2){
            for (Map map : list) {
                map.put("missionComments",redisData.get(map.get("missionId")));
            }
        }
        if(pageNum!=null && pageSize!=null){
            return Result.success(new PageInfo<>(list));
        }
        return Result.success(list);

    }
}




